'use strict'
const path = require('path')

function resolve(dir) {
  return path.join(__dirname, dir)
}

const CompressionPlugin = require('compression-webpack-plugin')

const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题

// 多环境后端接口配置
const getBaseUrl = () => {
  const env = process.env.NODE_ENV
  const customUrl = process.env.VUE_APP_API_URL

  if (customUrl) {
    return customUrl
  }

  switch (env) {
    case 'development':
      return process.env.VUE_APP_DEV_API_URL || 'http://localhost:8080'
    case 'production':
      return process.env.VUE_APP_PROD_API_URL || 'http://localhost:8080'
    default:
      return 'http://localhost:8080'
  }
}

const baseUrl = getBaseUrl()

const port = process.env.port || process.env.npm_config_port || 80 // 端口

// 代理配置错误处理
const createProxyConfig = (target) => ({
  target,
  changeOrigin: true,
  timeout: 30000, // 30秒超时
  logLevel: 'debug',
  secure: false,
  // 错误处理
  onError: (err, req, res) => {
    // 如果响应已经开始，不再尝试发送错误
    if (res.headersSent) {
      console.error('代理错误: 响应已发送，无法返回错误信息', err.message);
      return;
    }
    console.error('代理错误:', err.message)
    console.error('请求URL:', req.url)
    console.error('目标服务器:', target)

    // 返回友好的错误信息
    res.writeHead(500, {
      'Content-Type': 'application/json',
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE,OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization, Content-Length, X-Requested-With'
    })

    res.end(JSON.stringify({
      code: 500,
      // msg: `后端服务连接失败，请检查后端服务是否启动 (${target})`,
      msg: '',
      data: null
    }))
  },
  // 请求前处理
  onProxyReq: (proxyReq, req, res) => {
    console.log(`代理请求: ${req.method} ${req.url} -> ${target}${req.url}`)
  },
  // 响应后处理
  onProxyRes: (proxyRes, req, res) => {
    // 添加CORS头
    proxyRes.headers['Access-Control-Allow-Origin'] = '*'
    proxyRes.headers['Access-Control-Allow-Methods'] = 'GET,PUT,POST,DELETE,OPTIONS'
    proxyRes.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization, Content-Length, X-Requested-With'
  }
})

// vue.config.js 配置说明
//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
// 这里只列一部分，具体配置参考文档
module.exports = {
  // 部署生产环境和开发环境下的URL。
  // 默认情况下，Vue CLI 会假设你的应用是被部署在一个域名的根路径上
  // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上，你就需要用这个选项指定这个子路径。例如，如果你的应用被部署在 https://www.ruoyi.vip/admin/，则设置 baseUrl 为 /admin/。
  publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
  // 在npm run build 或 yarn build 时 ，生成文件的目录名称（要和baseUrl的生产环境路径一致）（默认dist）
  outputDir: 'dist',
  // 用于放置生成的静态资源 (js、css、img、fonts) 的；（项目打包之后，静态资源会放在这个文件夹下）
  assetsDir: 'static',
  // 如果你不需要生产环境的 source map，可以将其设置为 false 以加速生产环境构建。
  productionSourceMap: false,
  transpileDependencies: ['quill'],
  // webpack-dev-server 相关配置
  devServer: {
    host: '0.0.0.0',
    port: port,
    open: process.env.VUE_APP_AUTO_OPEN !== 'false',
    // 显示编译进度
    progress: true,
    // 热重载
    hot: true,
    // 压缩
    compress: true,
    // 错误覆盖
    overlay: {
      warnings: false,
      errors: true
    },
    proxy: {
      // detail: https://cli.vuejs.org/config/#devserver-proxy
      [process.env.VUE_APP_BASE_API]: {
        ...createProxyConfig(baseUrl),
        pathRewrite: {
          ['^' + process.env.VUE_APP_BASE_API]: ''
        }
      },
      // springdoc proxy
      '^/v3/api-docs/(.*)': createProxyConfig(baseUrl),
      // 健康检查接口
      '^/actuator/health': createProxyConfig(baseUrl),
      // 信用系统API代理
      '^/credit/(.*)': createProxyConfig(baseUrl)
    },
    disableHostCheck: true,
    // 开发服务器启动前检查后端服务
    before: (app, server, compiler) => {
      console.log('=================================')
      console.log('🚀 前端开发服务器启动中...')
      console.log(`📍 前端地址: http://localhost:${port}`)
      console.log(`🔗 后端地址: ${baseUrl}`)
      console.log(`🌍 环境: ${process.env.NODE_ENV}`)
      console.log('=================================')

      // 添加后端服务状态检查接口
      // app.get('/api/server-status', async (req, res) => {
      //   try {
      //     const http = require('http')
      //     const url = require('url')
      //     const parsed = url.parse(baseUrl)
      //
      //     const options = {
      //       hostname: parsed.hostname,
      //       port: parsed.port || 8080,
      //       path: '/actuator/health',
      //       method: 'GET',
      //       timeout: 5000
      //     }
      //
      //     const request = http.request(options, (response) => {
      //       res.json({
      //         code: 200,
      //         msg: '后端服务正常',
      //         data: {
      //           status: 'UP',
      //           url: baseUrl
      //         }
      //       })
      //     })
      //
      //     request.on('error', (error) => {
      //       res.json({
      //         code: 500,
      //         msg: '后端服务连接失败',
      //         data: {
      //           status: 'DOWN',
      //           url: baseUrl,
      //           error: error.message
      //         }
      //       })
      //     })
      //
      //     request.on('timeout', () => {
      //       res.json({
      //         code: 500,
      //         msg: '后端服务连接超时',
      //         data: {
      //           status: 'TIMEOUT',
      //           url: baseUrl
      //         }
      //       })
      //     })
      //
      //     request.end()
      //   } catch (error) {
      //     res.json({
      //       code: 500,
      //       msg: '服务检查失败',
      //       data: {
      //         status: 'ERROR',
      //         error: error.message
      //       }
      //     })
      //   }
      // })
    }
  },
  css: {
    loaderOptions: {
      sass: {
        sassOptions: { outputStyle: "expanded" }
      }
    }
  },
  configureWebpack: {
    name: name,
    resolve: {
      alias: {
        '@': resolve('src')
      }
    },
    plugins: [
      // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件
      new CompressionPlugin({
        cache: false,                                  // 不启用文件缓存
        test: /\.(js|css|html|jpe?g|png|gif|svg)?$/i,  // 压缩文件格式
        filename: '[path][base].gz[query]',            // 压缩后的文件名
        algorithm: 'gzip',                             // 使用gzip压缩
        minRatio: 0.8,                                 // 压缩比例，小于 80% 的文件不会被压缩
        deleteOriginalAssets: false                    // 压缩后删除原文件
      })
    ],
    // 开发环境性能优化
    ...(process.env.NODE_ENV === 'development' && {
      devtool: 'eval-cheap-module-source-map',
      optimization: {
        splitChunks: {
          chunks: 'all',
          minSize: 0,
          cacheGroups: {
            vendor: {
              test: /[\\/]node_modules[\\/]/,
              name: 'vendors',
              chunks: 'all',
            }
          }
        }
      }
    })
  },
  chainWebpack(config) {
    config.plugins.delete('preload') // TODO: need test
    config.plugins.delete('prefetch') // TODO: need test

    // set svg-sprite-loader
    config.module
      .rule('svg')
      .exclude.add(resolve('src/assets/icons'))
      .end()
    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add(resolve('src/assets/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })
      .end()

    // 开发环境优化
    if (process.env.NODE_ENV === 'development') {
      config.optimization.splitChunks({
        chunks: 'all',
        cacheGroups: {
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            name: 'vendors',
            chunks: 'all',
          }
        }
      })
    }

    config.when(process.env.NODE_ENV !== 'development', config => {
          config
            .plugin('ScriptExtHtmlWebpackPlugin')
            .after('html')
            .use('script-ext-html-webpack-plugin', [{
            // `runtime` must same as runtimeChunk name. default is `runtime`
              inline: /runtime\..*\.js$/
            }])
            .end()

          config.optimization.splitChunks({
            chunks: 'all',
            cacheGroups: {
              libs: {
                name: 'chunk-libs',
                test: /[\\/]node_modules[\\/]/,
                priority: 10,
                chunks: 'initial' // only package third parties that are initially dependent
              },
              elementUI: {
                name: 'chunk-elementUI', // split elementUI into a single package
                test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm
                priority: 20 // the weight needs to be larger than libs and app or it will be packaged into libs or app
              },
              commons: {
                name: 'chunk-commons',
                test: resolve('src/components'), // can customize your rules
                minChunks: 3, //  minimum common number
                priority: 5,
                reuseExistingChunk: true
              }
            }
          })
          config.optimization.runtimeChunk('single')
    })
  }
}
